#ifndef SERVER_H
#define SERVER_H

#include <QObject>
#include <QHttpServer>
#include <QProtobufSerializer>
#include <QWebSocketServer>
#include <QFile>
#include <QFileInfo>
#include <QPixmap>
#include <QIcon>


/*******************************************************************************************************************/
/****工具函数  后续很多模块都要用到**************************************************************************************/
/*******************************************************************************************************************/

//从文件路径中获取文件名
static inline QString getFileName(const QString& path){
    QFileInfo fileInfo(path);
    return fileInfo.fileName();
}

//封装一个"宏"作为打印日志的方式(可以看出在哪个文件的第几行出错)-->定义宏后不要加";"号
#define TAG QString("[%1:%2]").arg(getFileName(__FILE__),QString::number(__LINE__))
//qDebug打印字符串,会自动加上"",通过noquote()方法使输出对象不再加""
#define LOG() qDebug().noquote() << TAG

//得到格式化时间,将时间戳转化成格式化时间-->Qt中提供QDateTime类来处理时间
static inline QString formatTime(int64_t timestamp){
    //先把时间戳转化成QDateTime对象
    QDateTime dateTime = QDateTime::fromMSecsSinceEpoch(timestamp);
    //把QDateTime对象转化成"格式化时间"并返回
    return dateTime.toString("MM-dd HH:mm:ss");
}

//获取当前 秒级 时间戳
static inline int64_t getTime(){
    return QDateTime::currentSecsSinceEpoch();
}

//根据QByteArry转成QIcon-->借用QPixmap来实现
static inline QIcon makeIcon(const QByteArray& byteArray){
    QPixmap pixmap;
    pixmap.loadFromData(byteArray);
    QIcon icon(pixmap);
    return icon;
}

//读写文件操作
//从指定文件中,读取所有二进制内容,得到一个QByteArray
static inline QByteArray loadFileTOByteArray(const QString& path){
    QFile file(path);
    bool ret = file.open(QFile::ReadOnly);
    if(!ret) {
        LOG() << "文件打开失败!";
        file.close();
        return QByteArray();
    }
    QByteArray content = file.readAll();
    file.close();
    return content;
}

//把一个QByteArray中的内容,写入到某个指定文件里
static inline void writeByteArrayToFile(const QString& path,const QByteArray& content){
    QFile file(path);
    bool ret = file.open(QFile::WriteOnly);
    if(!ret) {
        LOG() << "文件打开失败!";
        file.close();
        return;
    }
    file.write(content);
    file.flush();       //刷新缓冲区,写完如果不刷新缓存区,很有可能要写入的数据没有写入硬盘,依旧在缓冲区里
    file.close();
}

/////////////////////////////////////////////////////////////////////////////////////
/// HTTP 服务器
/////////////////////////////////////////////////////////////////////////////////////

class HttpServer : public QObject
{
    Q_OBJECT

private:
    //单例化模式
    static HttpServer* instance;
    //构造函数
    HttpServer(){};
    //HTTP服务器
    QHttpServer httpServer;
    //序列化器
    QProtobufSerializer serializer;

public:
    //获取实例
    static HttpServer* getInstance();
    //初始化httpServer(http服务器)-->绑定端口,配置路由......
    bool init();
    //获取个人用户信息
    QHttpServerResponse getUserInfo(const QHttpServerRequest& req);
    //获取好友列表
    QHttpServerResponse getFriendList(const QHttpServerRequest& req);
    //获取会话列表
    QHttpServerResponse getChatSessionList(const QHttpServerRequest& req);
    //获取好友申请列表
    QHttpServerResponse getApplyList(const QHttpServerRequest& req);
    //获取指定会话的最近历史消息列表
    QHttpServerResponse getRecent(const QHttpServerRequest& req);
    //处理从客户端发送消息
    QHttpServerResponse newMessage(const QHttpServerRequest& req);
    //处理修改个人信息的昵称
    QHttpServerResponse setNickname(const QHttpServerRequest& req);
    //处理修改个人信息的个性签名
    QHttpServerResponse setDescription(const QHttpServerRequest& req);
    //处理获取短信验证码
    QHttpServerResponse getPhoneVerifyCode(const QHttpServerRequest& req);
    //处理修改个人信息的手机号
    QHttpServerResponse setPhone(const QHttpServerRequest& req);
    //处理修改个人信息的头像
    QHttpServerResponse setAvatar(const QHttpServerRequest& req);
    //处理删除好友
    QHttpServerResponse removeFriend(const QHttpServerRequest& req);
    //处理添加好友申请
    QHttpServerResponse addFriendApply(const QHttpServerRequest& req);
    //对添加好友申请的处理
    QHttpServerResponse addFriendProcess(const QHttpServerRequest& req);
    //处理创建会话申请
    QHttpServerResponse createChatSession(const QHttpServerRequest& req);
    //获取会话成员列表
    QHttpServerResponse getChatSessionMember(const QHttpServerRequest& req);
    //获取搜索用户结果
    QHttpServerResponse searchFriend(const QHttpServerRequest& req);
    //获取搜索历史消息结果
    QHttpServerResponse searchHistory(const QHttpServerRequest& req);
    //获取按时间搜索历史消息结果
    QHttpServerResponse getHistory(const QHttpServerRequest& req);
    //用户名登录请求
    QHttpServerResponse usernameLogin(const QHttpServerRequest& req);
    //用户名注册请求
    QHttpServerResponse usernameRegister(const QHttpServerRequest& req);
    //电话登录请求
    QHttpServerResponse phoneLogin(const QHttpServerRequest& req);
    //用户名注册请求
    QHttpServerResponse phoneRegister(const QHttpServerRequest& req);
    //获取单个文件
    QHttpServerResponse getSingleFile(const QHttpServerRequest& req);
    //语音转文字
    QHttpServerResponse recognition(const QHttpServerRequest& req);
};

/////////////////////////////////////////////////////////////////////////////////////
/// Websocket 服务器
/////////////////////////////////////////////////////////////////////////////////////

class WebsocketServer : public QObject{
    Q_OBJECT
private:
    //单例化模式
    static WebsocketServer* instance;
    //构造函数
    WebsocketServer() : websocketServer("websocket server" , QWebSocketServer::NonSecureMode){};
    //Websocket服务器
    QWebSocketServer websocketServer;
    //序列化器
    QProtobufSerializer serializer;
    //记录消息的下标
    int messageIndex = 0;
public:
    //获取实例
    static WebsocketServer* getInstance();
    //初始化WebsocketServer(Websocket服务器)-->连接信号槽,绑定端口
    bool init();
signals:
    void sendTextResp();            //通知websocket发送文本消息给客户端
    void sendImageResp();           //通知websocket发送图片消息给客户端
    void sendFileResp();            //通知websocket发送文件消息给客户端
    void sendSpeechResp();          //通知websocket发送语音消息给客户端
    void sendFriendRemove();        //通知websocket发送删除好友的通知给客户端
    void sendAddFriendApply();      //通知websocket发送申请好友的通知给客户端
    void sendAddFriendProcess(bool agree);  //通知websocket发送申请好友的结果通知给客户端
    void sendCreateChatSession();   //通知websocket发送创建会话的通知给客户端
};


#endif // SERVER_H
